﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using SubsDownloader.Core.Entities;
using SubsDownloader.Core.EventArgs;

namespace SubsDownloader.Core.Providers
{
    public class SubsCenterProvider : SubtitlesProvider
    {
        private const string SearchUrl = "http://www.subscenter.org/he/subtitle/search/?q=";
        private const string SiteUrl = "http://www.subscenter.org/";
        private const int Timeout = 200000;
        private const string InPageXPath = "/html/body/div[@id='wrapper']/div[@id='siteWrapper']/div[@id='sitePart']/div[@id='content']/div[@class='pageTop']/div[@class='pageTitle']/h3";       
        private const string IsSeriesXPath = "/html/body/div[@id='wrapper']/div[@id='siteWrapper']/div[@id='sitePart']/div[@id='content']/div[@id='currentPath']/a[2]";

        public override string Name
        {
            get { return "SubsCenter"; }
        }

        protected override TitleResult[] FindTitles ( TitleFileInfo titleFileInfo )
        {
            HttpWebRequest request;
            HttpWebResponse response = null;
            StreamReader reader = null;

            try
            {
                request = (HttpWebRequest)WebRequest.Create( SearchUrl + titleFileInfo.TitleName );
                request.Timeout = Timeout;
                response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader( response.GetResponseStream() );
                string html = reader.ReadToEnd();
                List<TitleResult> titleResults = new List<TitleResult>();
                TitleResult[] results = AnalyzeMovieResults( html, response, titleFileInfo );
                if (results == null)
                    return null;

                titleResults.AddRange( results );
                var pageCount = 2;
                
                var nextPageMatch = Regex.Match( html, string.Format( "/?q={0}&page={1}",titleFileInfo.TitleName,pageCount  ) );
                while (nextPageMatch.Success)
                {
                    request = (HttpWebRequest)WebRequest.Create( SearchUrl + string.Format( "{0}&page={1}", titleFileInfo.TitleName, pageCount ) );
                    request.Timeout = Timeout;
                    response = (HttpWebResponse)request.GetResponse();
                    reader = new StreamReader( response.GetResponseStream() );
                     html = reader.ReadToEnd();

                    var nextPageResults = AnalyzeMovieResults( html, response, titleFileInfo );
                    titleResults.AddRange( nextPageResults );
                    pageCount++;
                    nextPageMatch = Regex.Match( html, string.Format( "/?q={0}&page={1}", titleFileInfo.TitleName, pageCount ) );
                }
                return titleResults.ToArray();
            }
            catch (TimeoutException)
            {
                InvokeProgressChanged( new SubsProgressEventArgs( titleFileInfo, 0, "GetTitles Timeout" ) );
                return null;
            }
            catch (Exception e)
            {
                InvokeProgressChanged( new SubsProgressEventArgs( titleFileInfo, 0, e.Message ) );
                return null;
            }
            finally
            {
                if (response != null)
                    response.Close();
                if (reader != null)
                {
                    reader.Close();
                    reader.Dispose();
                }
            }
        }

        protected override SubtitleResult[] FindSubtitles ( TitleFileInfo title, TitleResult movieResult )
        {
            HttpWebRequest request;
            HttpWebResponse response = null;
            StreamReader reader = null;
            try
            {
                request = (HttpWebRequest)WebRequest.Create( movieResult.Url );
                request.Timeout = Timeout;
                response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader( response.GetResponseStream() );
                string html = reader.ReadToEnd();

                if (title.IsSeries)
                {
                    var match = Regex.Match( html, @"var movie_slug = '(?<movieName>.*?)';", RegexOptions.Singleline );
                    if (match.Success)
                    {
                        string movieName = match.Groups["movieName"].Value;                     
                         string subsUrl = string.Format( "http://www.subscenter.org/he/subtitle/series/{0}/{1}/{2}/", movieName, title.Season.TrimStart( '0' ), title.Episode.TrimStart( '0' ) );
                        request = (HttpWebRequest)WebRequest.Create( subsUrl );
                        request.Timeout = Timeout;
                        response = (HttpWebResponse)request.GetResponse();
                        reader = new StreamReader( response.GetResponseStream() );
                        html = reader.ReadToEnd();
                    }
                }
                var match2 = Regex.Match( html, "he\":.*?\"subtitle_version\": .*?subtitles_info", RegexOptions.Singleline | RegexOptions.IgnoreCase );
                if (match2.Success)
                {
                    var subtitleResults = new List<SubtitleResult>();
                    var match3 = Regex.Matches( match2.Value, "{\"created_by\":.*?, \"subtitle_version\": .*?}" );
                    foreach (Match innerMatch in match3)
                    {
                        var matchId = Regex.Match( innerMatch.Value, "id\": (?<id>\\d+)" );
                        var matchkey = Regex.Match( innerMatch.Value, "key\": (?<key>.*?)," );
                        var matchSubs = Regex.Match( innerMatch.Value, "subtitle_version\": (?<subs>.*?)," );
                       
                        var subtitleResult = new SubtitleResult( title );
                        subtitleResult.CDCount = "0";
                        subtitleResult.Link = string.Format( "http://www.subscenter.org/he/subtitle/download/he/{0}/?v={1}&key={2}", matchId.Groups["id"].Value, matchSubs.Groups["subs"].Value.Trim( '"' ), matchkey.Groups["key"].Value.Trim( '"' ) );
                        subtitleResult.Name = matchSubs.Groups["subs"].Value.Trim( '"' );
                        subtitleResults.Add( subtitleResult );
                    }
                    return subtitleResults.ToArray();
                }
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                if (response != null)
                    response.Close();
                if (reader != null)
                {
                    reader.Close();
                    reader.Dispose();
                }
            }
            return null;
        }

        private TitleResult[] AnalyzeMovieResults ( string html, HttpWebResponse response, TitleFileInfo title )
        {
            var titleResults = new List<TitleResult>();
            var document = new HtmlDocument();
            document.LoadHtml( html );
            var notExistsElement = document.DocumentNode.SelectSingleNode( "/html/body/div[@id='wrapper']/div[@id='siteWrapper']/div[@id='sitePart']/div[@id='content']/div[@id='processesTitle']" );
            if (notExistsElement != null)
            {
                var innerText = notExistsElement.InnerText.Trim();
                if (innerText == "לא נמצאו תוצאות העונות לבקשתך")
                {
                    return null;
                }
            }
            var inPageNodes = document.DocumentNode.SelectSingleNode( InPageXPath );
            if (inPageNodes != null)
            {
                var titleResult = new TitleResult( title );
                var isSeries = document.DocumentNode.SelectSingleNode( IsSeriesXPath );

                titleResult.IsSeries = isSeries.InnerText != "סרטים";
                titleResult.Url = response.ResponseUri.AbsoluteUri;
                titleResult.Name = inPageNodes.InnerText;
                titleResults.Add( titleResult );
                return titleResults.ToArray();
            }

            var nodeCollection = document.DocumentNode.SelectNodes( "/html/body/div[@id='wrapper']/div[@id='siteWrapper']/div[@id='sitePart']/div[@id='content']/div[@id='processes']/div[@class='generalWindow process movieProcess']" );
            foreach (HtmlNode node in nodeCollection)
            {
                var titleResult = new TitleResult( title );
                var aNodes = node.SelectSingleNode( "div/div/a" );
                string href = aNodes.Attributes["href"].Value;
                titleResult.Url = SiteUrl + href;

                var names = aNodes.InnerText.Split( '/' );
                titleResult.Name = names[1].Trim();

                //if name is long they add ... so try to export the name from the link
                if (titleResult.Name.EndsWith( "..." ))
                {
                    href = href.Trim( '/' );
                    int lastIndex = href.LastIndexOf( '/' ) + 1;
                    titleResult.Name = href.Substring( lastIndex, href.Length - lastIndex );
                    titleResult.Name = titleResult.Name.Replace( '-', ' ' );
                }

                var typeNode = node.SelectSingleNode( "div[2]/div/div/span[3]" );
                titleResult.IsSeries = typeNode.InnerText.Trim() == "סדרה";
                titleResults.Add( titleResult );
            }

            return titleResults.ToArray();
        }

    }
}
